package math.region;

import math.math;
import math.vec2;
import math.vec3;
import static math.vec3.*;

public class Plane3 implements Surface3
{
    
    public vec3 mOrig;
    
    public vec3 mNorm;
    
    
    public Plane3()
    {
        this.mOrig = new vec3();
        this.mNorm = new vec3();
    }
    
    public Plane3(
            vec3 aOrig, 
            vec3 aNormal)
    {
        this();
        this.set(aOrig, aNormal);
    }
    
    
    public final void set(
            vec3 aOrig, 
            vec3 aNormal)
    {
        this.mOrig.set(aOrig);
        this.setNormal(aNormal);
    }
    
    public final void set(Plane3 aOther)
    {
        this.set(aOther.mOrig, aOther.mNorm);
    }
    
    public final void setNormal(vec3 aNormal)
    {
        this.mNorm.set(aNormal);
        this.mNorm.norm();
    }
    
    
    public boolean regionContains(vec3 aPoint)
    {
        vec3 localPt = vec3.sub(aPoint, this.mOrig);
        boolean onNormSide = dot(localPt, this.mNorm) >= 0.0;
        return onNormSide;
    }
    
    public boolean onSurface(vec3 aPoint)
    {
        vec3 localPt = vec3.sub(aPoint, this.mOrig);
        double dot = dot(localPt, this.mNorm);
        boolean onPlane = math.abs(dot) < math.EPSILON;
        return onPlane;
    }
    
    
    public double surfaceArea()
    {
        
        return 1;
    }
    
    
    public vec3 surfaceNorm(
            vec3 aPoint, 
            vec3 aReferencePt)
    {
        vec3 localRefPt = vec3.sub(aReferencePt, this.mOrig);
        boolean onNormSide = dot(localRefPt, this.mNorm) >= 0.0;
        if (onNormSide)
        {
            return this.mNorm.copy();
        }
        return vec3.mul(-1, this.mNorm);
    }
    
    public vec3 convertParam_World(vec2 aUV)
    {
        return this.mOrig;
//        return null;
    }
    
    public vec2 convertWorld_Param(vec3 aPos)
    {
        return vec2.ZERO;
//        return null;
    }
    
    
    public Surface3 lerp(Surface3 next, double t)
    {
        return null;
    }
    
    
    public AABB3 boundingBox()
    {
        return null;
    }
    
    
    public Plane3 copy()
    {
        Plane3 copy = new Plane3();
        copy.set(this);
        return copy;
    }
    
    
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        sb.append("Plane3\n   Orig: ");
        sb.append(this.mOrig);
        sb.append("\n   Norm: ");
        sb.append(this.mNorm);
        return sb.toString();
    }
    
}
